/*
 * -----------------------------------------------------------------------------
 * Project    : Memory Support
 * Purpose    : Provide support for memory allocation of objects
 * File       : Win32.MemoryObject.h
 * Author     : Eduardo Sobrino
 * Date       : Nov/98
 * LastUpdate : Jun/2k6 (Revice code from previous version)
 */

#pragma once

// -----------------------------------------------------------------------------

#include "Win32.MemoryBuffer.h"
#include "Win32.Types.h"
#include "Win32.DateTime.h"

namespace Kif
{
namespace Win32
{

enum ObjectCompatibility
{
   Object_Compatible = 1,
   Object_LossOfPrecision = 2,
   Object_Incompatible = 3,
   Object_WillBeTruncated = 4
}  ;  // end of MemoryObjectCompatibility

class MemoryObject
{
private:
   bool disposable;
   Kif::Win32::MemoryBuffer<BYTE> memBuffer;
   Kif::Win32::BaseType type;
   DWORD typeSize;

   void setValue(void *value, Kif::Win32::BaseType type, DWORD size);
   void setValue(void *value, Kif::Win32::BaseType type)
   {  setValue(value,type,0); }

public:

   static const int MaxSize = 1024;

   MemoryObject(Kif::Win32::BaseType type, DWORD size, bool disposable);
   MemoryObject(Kif::Win32::BaseType type)
   {
      MemoryObject(type,MaxSize+1,true);
   }

  ~MemoryObject()
   {
      memBuffer.Dispose();
   }

   #pragma region // Define Type and Size management functions

   inline Kif::Win32::BaseType GetType()
   {
      return(type);
   }
   inline DWORD GetSizeInBytes()
   {
      return((DWORD)memBuffer.GetSize());
   }
   inline DWORD GetSize()
   {
      DWORD sz = SizeOfType(type);
      if (sz == 0)
         return(0);
      return((DWORD)memBuffer.GetSize()/sz);
   }

   inline DWORD SizeOfType(Kif::Win32::BaseType type)
   {
      DWORD sz = 0;
      switch(type)
      {
         case Kif::Win32::BaseType_Boolean:
            sz = sizeof(bool);
            break;
         case Kif::Win32::BaseType_Int16:
            sz = sizeof(short);
            break;
         case Kif::Win32::BaseType_Int32:
            sz = sizeof(long);
            break;
         case Kif::Win32::BaseType_Float:
            sz = sizeof(float);
            break;
         case Kif::Win32::BaseType_Double:
            sz = sizeof(double);
            break;
         case Kif::Win32::BaseType_AnsiString:
            sz = sizeof(char);
            break;
         case Kif::Win32::BaseType_WideString:
            sz = sizeof(wchar_t);
            break;
         case Kif::Win32::BaseType_DateTime:
            sz = sizeof(Kif::Win32::TIMESTAMP_STRUCT);
            break;
         case Kif::Win32::BaseType_Byte:
         case Kif::Win32::BaseType_Blob:
            sz = sizeof(BYTE);
            break;
      }
      return(sz);
   }  // end of SizeOfType

   inline DWORD SizeOfType()
   {
      return(SizeOfType(type));
   }  // end of SizeOfType

   #pragma endregion
   #pragma region // Define Is-A functions

   inline bool IsInteger(Kif::Win32::BaseType type)
   {
      bool itis = false;
      switch(type)
      {
         case Kif::Win32::BaseType_Boolean:
         case Kif::Win32::BaseType_Int16:
         case Kif::Win32::BaseType_Int32:
            itis = true;
            break;
      }
      return(itis);
   }  // end of IsInteger

   inline bool IsNumeric(Kif::Win32::BaseType type)
   {
      bool itis = false;
      switch(type)
      {
         case Kif::Win32::BaseType_Boolean:
         case Kif::Win32::BaseType_Int16:
         case Kif::Win32::BaseType_Int32:
         case Kif::Win32::BaseType_Float:
         case Kif::Win32::BaseType_Double:
            itis = true;
            break;
      }
      return(itis);
   }  // end of IsNumeric

   inline bool IsFloat(Kif::Win32::BaseType type)
   {
      bool itis = false;
      switch(type)
      {
         case Kif::Win32::BaseType_Float:
         case Kif::Win32::BaseType_Double:
            itis = true;
            break;
      }
      return(itis);
   }  // end of IsFloat

   inline bool IsString(Kif::Win32::BaseType type)
   {
      bool itis = false;
      switch(type)
      {
         case Kif::Win32::BaseType_AnsiString:
         case Kif::Win32::BaseType_WideString:
            itis = true;
            break;
      }
      return(itis);
   }  // end of IsString

   inline bool IsDateTime(Kif::Win32::BaseType type)
   {
      bool itis = false;
      switch(type)
      {
         case Kif::Win32::BaseType_DateTime:
            itis = true;
            break;
      }
      return(itis);
   }  // end of IsDateTime

   inline bool IsBoolean(Kif::Win32::BaseType type)
   {
      bool itis = false;
      switch(type)
      {
         case Kif::Win32::BaseType_Boolean:
            itis = true;
            break;
      }
      return(itis);
   }  // end of IsBoolean

   inline bool IsBlob(Kif::Win32::BaseType type)
   {
      bool itis = false;
      switch(type)
      {
         case Kif::Win32::BaseType_Blob:
            itis = true;
            break;
      }
      return(itis);
   }  // end of IsBlob

   inline bool IsBlob()
   {
      return(IsBlob(type));
   }  // end of IsBlob

   inline bool IsInteger()
   {
      return(IsInteger(type));
   }  // end of IsInteger

   inline bool IsFloat()
   {
      return(IsFloat(type));
   }  // end of IsFloat

   inline bool IsNumeric()
   {
      return(IsNumeric(type));
   }  // end of IsNumeric

   inline bool IsDateTime()
   {
      return(IsDateTime(type));
   }  // end of IsDateTime

   inline bool IsBoolean()
   {
      return(IsBoolean(type));
   }  // end of IsBoolean

   inline bool IsString()
   {
      return(IsString(type));
   }  // end of IsString

   #pragma endregion

   Kif::Win32::ObjectCompatibility
      Compatible(Kif::Win32::BaseType type, DWORD size);
   Kif::Win32::ObjectCompatibility Compatible(Kif::Win32::BaseType type)
   {
      return(Compatible(type,0));
   }

   inline void setValue(bool value)
   {  setValue(&value,Kif::Win32::BaseType_Boolean); }
   inline void setValue(short value)
   {  setValue(&value,Kif::Win32::BaseType_Int16); }
   inline void setValue(int value)
   {  setValue(&value,Kif::Win32::BaseType_Int32); }
   inline void setValue(Kif::Win32::DateTime *value)
   {  setValue(value,Kif::Win32::BaseType_DateTime); }
   inline void setValue(Kif::Win32::DateTime &value)
   {  setValue(&value,Kif::Win32::BaseType_DateTime); }
   inline void setValue(long value)
   {  setValue(&value,Kif::Win32::BaseType_Int32); }
   inline void setValue(char *value, DWORD size)
   {  setValue(value,Kif::Win32::BaseType_AnsiString,size); }
   inline void setValue(TCHAR *value, DWORD size)
   {  setValue(value,Kif::Win32::BaseType_WideString,size); }
   inline void setValue(BYTE *value, DWORD size)
   {  setValue(value,Kif::Win32::BaseType_Blob,size); }

   inline void *getValue()
   {
      return(memBuffer.Buffer);
   }

   inline long AsLong()
   {
      long *l = (long*)memBuffer.Buffer;
      return(*l);
   }

   inline char* AsAnsiString()
   {
      return((char*)memBuffer.Buffer);
   }

   inline wchar_t* AsWideString()
   {
      return((wchar_t*)memBuffer.Buffer);
   }

}  ;  // end of MemoryObject

}
}
